#include "CorelSpyAPI.h"

#pragma comment(lib, "../Detour/Lib/Detours.lib")
#pragma comment(lib, "../Detour/Lib/Detoured.lib")
#pragma comment(lib, "../DbgHelp/Lib/i386/dbghelp.lib")
#pragma comment(lib, "psapi.lib")

CRITICAL_SECTION g_csGlobInit;
BOOL g_bGlobInited = FALSE;
DWORD g_dwSpyEnableTlsIndex = (DWORD)-1;
CCorelSpyMediator *g_pcMediator = NULL;
CCorelSpyAPIProxy *g_pcAPIProxy = NULL;

// This exported api is used to bypass the ordinal 1 limitation for using MS Detours library.
// Don't remove it!!!
__declspec (dllexport) int SetVersion(int iMajor, int iMinor, int iBuild)
{
    return 0;
}

BOOL GlobInit()
{
    EnterCriticalSection(&g_csGlobInit);
    if (TRUE == g_bGlobInited)
    {
        LeaveCriticalSection(&g_csGlobInit);
        return g_bGlobInited;
    }

    // To workaround the problem that LoadLibrary would reentry indefinitely
    if (g_csGlobInit.RecursionCount > 1)
    {
        LeaveCriticalSection(&g_csGlobInit);
        return FALSE;
    }

    g_pcMediator = new CCorelSpyMediator(g_dwSpyEnableTlsIndex);
    g_pcAPIProxy = new CCorelSpyAPIProxy(g_pcMediator);

    g_bGlobInited = TRUE;
    LeaveCriticalSection(&g_csGlobInit);

    return g_bGlobInited;
}


BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
{
    if (dwReason == DLL_PROCESS_ATTACH) 
    {
#ifdef _DEBUG
        ::Sleep(5000);
#endif

        InitializeCriticalSection(&g_csGlobInit);
        g_dwSpyEnableTlsIndex = TlsAlloc();
        TlsSetValue(g_dwSpyEnableTlsIndex, (LPVOID)TRUE);

        HRESULT hr = DetourAttach();
        if (SUCCEEDED(hr))
        {
            TrueOutputDebugStringA("DBGVIEWCLEAR");
            TrueOutputDebugStringA("[CorelSpy] Detour Attached!");
        }
    }
    else if (dwReason == DLL_PROCESS_DETACH) 
    {
        DeleteCriticalSection(&g_csGlobInit);

        HRESULT hr = DetourDetach();
        if (SUCCEEDED(hr))
        {
            TrueOutputDebugStringA("[CorelSpy] Detour Detached!");
        }
    }
    else if (dwReason == DLL_THREAD_ATTACH)
    {
        TlsSetValue(g_dwSpyEnableTlsIndex, (LPVOID)TRUE);
    }
    return TRUE;
}
